#include "thread_pool.h"
//遗书函数
void handler(void *arg)
{
    printf("[%u]：调用了遗书函数\n",(unsigned)pthread_self());
    pthread_mutex_unlock((pthread_mutex_t *)arg);//解锁线程
}

//线程执行函数
void *routine(void *arg)
{
    thread_pool *pool=(thread_pool *)arg;
    struct task *p;
    while(1)
    {
        pthread_cleanup_push(handler,(void *)&pool->lock);//准备好遗书函数
        pthread_mutex_lock(&pool->lock);//上锁

        //1.如果没有任务并且线程池没被销毁就解锁并进入等待队列
        while(pool->waiting_tasks==0&&!pool->shutdown)
        {
            pthread_cond_wait(&pool->cond,&pool->lock);
        }

        //2.如果没有任务并且线程池准备销毁，解锁并退出线程
        if(pool->waiting_tasks==0&&pool->shutdown==true)
        {
            pthread_mutex_unlock(&pool->lock);
            pthread_exit(NULL);
        }
        
        //从任务链队列中取出一个任务
        p=pool->task_list->next;
        pool->task_list->next=p->next;
        pool->waiting_tasks--;

        //解锁
        pthread_mutex_unlock(&pool->lock);
        pthread_cleanup_pop(0);

        //设置线程在执行任务时不允许销毁
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
        (p->do_task)(p->arg);
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);

        free(p);
    }
    //退出线程
    pthread_exit(NULL);
}

//初始化线程
bool init_pool(thread_pool *pool,unsigned int threads_number)
{
    pthread_mutex_init(&pool->lock,NULL); //初始化互斥锁
    pthread_cond_init(&pool->cond,NULL); //初始化条件变量
    pool->shutdown=false; //初始化线程销毁标记
    pool->task_list=calloc(1,sizeof(struct task));  //初始化任务链表
    pool->tids=calloc(MAX_ACTIVE_THREADS,sizeof(pthread_t));    //初始化线程tid

    if(pool->task_list==NULL||pool->tids==NULL)
    {
        perror("初始化任务链队或线程ID存放位置失败！");
        return false;
    }
    pool->task_list->next=NULL;
    pool->max_waiting_tasks=MAX_WAITING_TASKS;
    pool->waiting_tasks=0;
    pool->active_threads=threads_number;
    for(int i=0; i<pool->active_threads; i++)
	{
		if(pthread_create(&((pool->tids)[i]), NULL,
					routine, (void *)pool) != 0)
		{
			perror("create threads error");
			return false;
		}

		#ifdef DEBUG
		printf("[%u]:[%s] ==> tids[%d]: [%u] is created.\n",
			(unsigned)pthread_self(), __FUNCTION__,
			i, (unsigned)pool->tids[i]);
		#endif
	}
    return true;
}

bool add_task(thread_pool *pool,void *(*do_task)(void *arg),void *arg)
{
    //新建任务节点
    struct task *new_task=malloc(sizeof(struct task));
    if(new_task==NULL)
    {
        perror("新建任务节点失败!");
        return false;
    }
    new_task->do_task=do_task;
    new_task->arg=arg;
    new_task->next=NULL;

    //上锁
    pthread_mutex_lock(&pool->lock);

    //判断任务数是否达到上限
    if(pool->waiting_tasks>=MAX_WAITING_TASKS)
    {
        //任务过多，解锁后释放资源，退出
        pthread_mutex_unlock(&pool->lock);
        fprintf(stderr,"任务数过多，已达到任务数上限，新建任务失败！");
        free(new_task);
        return false;
    }
    //将新任务加入到任务链队列
    struct task *tmp=pool->task_list;
    while (tmp->next->next!=NULL)
    {
        tmp=tmp->next;
    }
    tmp->next=new_task;
    pool->waiting_tasks++;

    //解锁
    pthread_mutex_unlock(&pool->lock);

    pthread_cond_signal(&pool->cond);
    return true;

}